import os
import re
import sys

def read_file(file_path):
    """读取文件内容，处理编码问题"""
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            return file.read()
    except UnicodeDecodeError:
        with open(file_path, 'r', encoding='gbk') as file:
            return file.read()

def is_valid_segment_start(content, index):
    """检查给定索引前面的字符是否符合条件"""
    if index == 0:
        return True  # 开头的字符没有前置字符，视为有效
    
    prev_char = content[index - 1]
    # 定义有效的前置字符集合
    valid_chars = set("_\n\r\t -*/=<>!&|({[]}).:")
    return prev_char in valid_chars

def find_duplicates(name_dir, min_num, excl):
    """查找文件中的重复代码段"""
    duplicates = {}
    lst = list(name_dir.items())

    for target_filename, target_content in lst:
        print(f"正在处理的目标文件: {target_filename}")
        # 初始化目标文件的查重信息
        duplicates[target_filename] = {'duplicates': {}}  # 使用字典以存储与目标文件重复的文件及其代码段

        for check_filename, check_content in lst:
            if target_filename != check_filename:
                print(f"被与目标文件进行比对的文件: {check_filename}")
                i = 0
                while i < len(target_content) - min_num + 1:
                    # 找到非空格字符
                    if not target_content[i].isspace():
                        # 检查该字符前面的字符是否有效
                        if is_valid_segment_start(target_content, i):
                            code_segment = target_content[i:i + min_num]
                            if re.fullmatch(r'[a-zA-Z0-9\s+\-*/=<>!&|]+', code_segment) and not any(keyword in code_segment for keyword in excl):
                                if code_segment in check_content:
                                    # 将找到的代码段添加到字典中
                                    if check_filename not in duplicates[target_filename]['duplicates']:
                                        duplicates[target_filename]['duplicates'][check_filename] = []
                                    if code_segment not in duplicates[target_filename]['duplicates'][check_filename]:
                                        duplicates[target_filename]['duplicates'][check_filename].append(code_segment)
                        # 移动到下一个字符
                        i += 1
                    else:
                        # 如果当前字符是空格，直接移动到下一个字符
                        i += 1

    return duplicates

def main(folder_path):
    # 创建输出目录
    output_folder = os.path.join(folder_path, '输出结果')
    os.makedirs(output_folder, exist_ok=True)  # 创建文件夹，如果已存在则不会报错    
    # 初始化字典存储文件内容
    name_dir = {}
    excl = ['utf-8', 'input', 'tuinfomgr.txt', 'for', 'student', 'print', 'break', 'flag',
            'choice', 'True', 'False', 'if', 'elif', 'stuinfomgr', 'select', 'round', 'os.path.exists',
            'score', 'else', 'continue', 'while', 'def', 'return', 'with', 'as', 'open',
            'file', 'read', 'readlines', 'write', 'writelines', 'close', 'start', 'system',
            'os', 'rmdir', 'remove', 'exit', 'exit_program', 'main', 'work_directory', 'name', 'inp',
            'student_info_file', 'create_directory', 'create_student_info_file', 'encoding', 'txt', '.py',
            'split', 'lambda', '---', '===', '   ', ' = i', 'item in', 'except', 'import', 'in', 'range', 'true', 'Python', 'char', '==']
    min_num = 7

    # 遍历 .py 文件
    file_paths = [os.path.join(folder_path, file) for file in os.listdir(folder_path) if file.endswith('.py')]
    
    for file_path in file_paths:
        filename = os.path.basename(file_path)
        content = read_file(file_path)
        name_dir[filename] = content

    # 查找重复代码段
    duplicates = find_duplicates(name_dir, min_num, excl)

    # 输出结果到文件
    with open(os.path.join(output_folder, 'check_files.txt'), 'w', encoding='utf-8') as file:
        print(f'正在打印输出结果到check_files.txt中...')
        for target_filename, result in duplicates.items():
            file.write(f"------------------------------------------------------------\n")
            file.write(f"{target_filename}\n")
            if result['duplicates']:
                for name_list, obj_list in result['duplicates'].items():
                    file.write(f"存在的雷同文件：{name_list} \n")
                    for segment in obj_list:
                        file.write(f"       雷同片段：{segment}\n")
            else:
                file.write("没有与该文件重复的文件\n")
            file.write("\n")

    print("查重结果已写入 check_files.txt 文件中。")

if __name__ == "__main__":
    # folder_path = '测试数据集'  # 指定文件夹名称
    # main(folder_path)
    if len(sys.argv) < 2:
        print("请提供需要处理的文件夹路径。")
        sys.exit(1)

    folder_path = sys.argv[1]  # 从命令行参数获取文件夹路径
    main(folder_path)
